package tech.horgee.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.horgee.entity.Dept;
import tech.horgee.mapper.DeptMapper;
import tech.horgee.utils.AssertUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 部门表 服务类
 *
 * @author haojun
 * @since 2023-12-13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DeptService {
    private final DeptMapper mapper;

    /**
     * 分页查询列表
     *
     * @param page   分页对象
     * @param entity 查询实体
     * @return 所有数据
     */
    public Page<Dept> page(Page<Dept> page, Dept entity) {
        return mapper.selectPage(page, Optional.ofNullable(entity).orElse(new Dept()).wrapper());
    }

    /**
     * 不分页查询列表
     *
     * @param entity 实体对象
     * @return 查询结果
     */
    public List<Dept> list(Dept entity) {
        return mapper.selectList(Optional.ofNullable(entity).orElse(new Dept()).wrapper());
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    public Dept getById(Long id) {
        return mapper.selectById(id);
    }

    /**
     * 新增单条数据
     *
     * @param entity 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void save(Dept entity) {
        mapper.insert(entity);
    }

    /**
     * 修改单条数据
     *
     * @param entity 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(Dept entity) {
        AssertUtil.onlyOne(mapper.updateById(entity));
    }

    /**
     * 批量删除数据
     *
     * @param ids 主键集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteByIds(Set<Long> ids) {
        AssertUtil.updated(mapper.deleteBatchIds(ids));
    }

    public List<Dept> tree() {
        LambdaQueryWrapper<Dept> wrapper = new Dept().wrapper();
        wrapper.orderByAsc(Dept::getDeptSort);
        List<Dept> deptList = mapper.selectList(wrapper);
        return buildTree(deptList);
    }

    private List<Dept> buildTree(List<Dept> list) {
        if (CollUtil.isEmpty(list)) return Collections.emptyList();
        Map<Long, List<Dept>> parentIdMap = list.stream().collect(Collectors.groupingBy(Dept::getParentId));
        Long parentId = Collections.min(parentIdMap.keySet());
        List<Dept> depts = parentIdMap.get(parentId);
        return fillChildren(depts, parentIdMap);
    }

    private List<Dept> fillChildren(List<Dept> list, Map<Long, List<Dept>> parentIdMap) {
        return list.stream().peek(i -> {
            if (parentIdMap.containsKey(i.getDeptId())) {
                i.setChildren(fillChildren(parentIdMap.get(i.getDeptId()), parentIdMap));
            }
        }).collect(Collectors.toList());
    }

}
